﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;

namespace zijian666.Converts.Core;

/// <summary>
/// 异常收集器
/// </summary>
public sealed class ExceptionBuilder : List<Exception>
{
    /// <summary>
    /// 转换为 
    /// </summary>
    /// <param name="message"></param>
    /// <returns></returns>
    public AggregateException ToException(string message) => new MyAggregateException(message, this);

    /// <summary>
    /// 收集异常
    /// </summary>
    public static void Catch(ref ExceptionBuilder? ex1, Exception? ex2, string pattern)
    {
        if (ex2 is null)
        {
            return;
        }
        if (!string.IsNullOrWhiteSpace(pattern))
        {
            ex2.Data["Pattern"] = pattern;
        }
        if (ex1 is null)
        {
            ex1 = [ex2];
        }
        else
        {
            ex1.Add(ex2);
        }
    }

    class MyAggregateException(string? message, IEnumerable<Exception> innerExceptions)
        : AggregateException(message, innerExceptions)
    {
        string _message = message ?? throw new ArgumentNullException(nameof(message));
        public override string Message
        {
            get
            {
                var sb = new StringBuilder();
                if (Data["Pattern"] is string pattern && !string.IsNullOrWhiteSpace(pattern))
                {
                    sb.Append('[');
                    sb.Append(pattern);
                    sb.Append(']');
                    sb.Append(':');
                }
                if (!string.IsNullOrEmpty(_message))
                {
                    sb.AppendLine(_message);
                }
                AppendSubExceptions(sb, 2, this.InnerExceptions);


                return sb.ToString();
            }
        }

        private void AppendSubExceptions(StringBuilder sb, int tabs, IEnumerable<Exception> innerExceptions)
        {
            foreach (var ex in innerExceptions)
            {
                sb.Append(' ', tabs);
                sb.Append(" - ");
                if (ex.Data["Pattern"] is string pattern && !string.IsNullOrWhiteSpace(pattern))
                {
                    sb.Append('[');
                    sb.Append(pattern);
                    sb.Append(']');
                    sb.Append(':');
                }
                sb.AppendLine((ex as MyAggregateException)?._message ?? ex.Message);
                if (ex is AggregateException ae)
                {
                    AppendSubExceptions(sb, tabs + 2, ae.InnerExceptions);
                }
                else if (ex.InnerException is not null)
                {
                    AppendSubExceptions(sb, tabs + 2, [ex.InnerException]);
                }
            }
        }


        public override string ToString() => Message;
    }

}